package com.zgw.fireline.design.common;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Properties;

import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.internal.WorkbenchPlugin;

/**
 * 文件同步
 * */
public class FileUtil { 
	private File target;
	private File source;
	private Properties modifyRecord; // 源目录修改记录

	public FileUtil(File source, File target) {
		Assert.isTrue(source.exists() & source.isDirectory());
		Assert.isTrue(target.exists() & target.isDirectory());
		this.source = source;
		this.target = target;
	}

	public void run() throws IOException {
		File synFile = new File(target, ".syn.properties");
		if (!synFile.exists()) {
			synFile.createNewFile();
		}
		FileInputStream in = null;
		FileOutputStream out = null;
		modifyRecord = new Properties();
		try {
			in = new FileInputStream(synFile);
			modifyRecord.load(in);
			syn(source, target);
			out = new FileOutputStream(synFile);
			modifyRecord.store(out, "");
		} finally {
			if (in != null)
				in.close();
			if (out != null)
				out.close();
		}

	}

	/**
	 * @param source
	 *            源目录
	 * @param target
	 *            目标目录
	 * */
	private boolean syn(File source, File target) {
		Assert.isTrue(source.exists() & source.isDirectory());
		Assert.isTrue(target.exists() & target.isDirectory());
		boolean result = true;
		File s, t;
		long last_s = 0, length_s = 0, length_t = 0;
		// 删除目标目录中 源目录不存在的文件或目录
		for (String name : target.list()) {
			if (target == this.target && ".syn.properties".equals(name))
				continue;
			last_s = length_s = length_t = -1;
			s = new File(source, name);
			t = new File(target, name);
			if (t.exists()) {
				if (!s.exists() || (t.isDirectory() != s.isDirectory()))
					if (result = clear(t)) {
						System.out.println("删除路径:" + t.toString());
					} else if (Display.getCurrent() != null) {
						WorkbenchPlugin.log("删除文件失败:" + t.toString());
					}
			}
		}
		// 同步源目录
		for (String name : source.list()) {
			s = new File(source, name);
			t = new File(target, name);
			if (!s.exists()) { // 源文件不存在
				continue;
			} else if (t.exists() && s.isDirectory() & t.isDirectory() & true) { // 源文件和目标文件都存在
				result &= syn(s, t);
				continue;
			} else if (!t.exists() && s.isDirectory()) {
				result &= t.mkdir();
				result &= syn(s, t);
				continue;
			} else {
				last_s = s.lastModified();
				length_s = s.length();
			}
			if (t.exists()) {
				length_t = t.length();
			}
			if (!String.valueOf(last_s).equals(
					modifyRecord.getProperty(s.toString()))
					|| length_s != length_t) {
				try {
					copyFileBufferStream(s, t);
					modifyRecord.setProperty(s.toString(),
							String.valueOf(last_s));
					System.out.println("成功同步至:" + t.toString());
				} catch (IOException e) {
					if (Display.getCurrent() != null) {
						String message = new Date().toString();
						message += " 文件同步出错:" + e.getMessage();
						message += " /r/n源文件:" + s.toString();
						message += " /r/n目标文件:" + t.toString();
						WorkbenchPlugin.log(message);
					}
					result = false;
				}
			}
			result &= true;
		}

		return result;
	}

	public static boolean clear(java.io.File root) {
		boolean result = clearChildren(root);
		try {
			if (root.exists())
				result &= root.delete();
		} catch (Exception e) {
			result = false;
		}
		return result;
	}

	public static boolean clearChildren(java.io.File root) {
		boolean result = true;
		if (root.isDirectory()) {
			String[] list = root.list();
			// for some unknown reason, list() can return null.
			// Just skip the children If it does.
			if (list != null)
				for (int i = 0; i < list.length; i++)
					result &= clear(new java.io.File(root, list[i]));
		}
		return result;
	}

	public static final void copyFileBufferStream(File filename, File outFile)
			throws IOException {
		InputStream in = null;
		OutputStream out = new BufferedOutputStream(new FileOutputStream(
				outFile));
		try {
			in = new BufferedInputStream(new FileInputStream(filename));
			byte[] buf = new byte[1024 * 8];
			int bytesRead;
			while ((bytesRead = in.read(buf)) != -1) {
				out.write(buf, 0, bytesRead);
			}
			out.flush();

		} finally {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
		}
	}

	public static final void copyFileBufferStream(InputStream stream,
			File outFile) throws IOException {
		InputStream in = null;
		OutputStream out = new BufferedOutputStream(new FileOutputStream(
				outFile));
		try {
			in = new BufferedInputStream(stream);
			byte[] buf = new byte[1024 * 8];
			int bytesRead;
			while ((bytesRead = in.read(buf)) != -1) {
				out.write(buf, 0, bytesRead);
			}
			out.flush();

		} finally {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
		}
	}

	public static void main(String[] args) {
		File s = new File(
				"D:/servers/fy_test-tomcat-5.5.27/webapps/com.ztkj.his.main.server");
		File t = new File("E:/com.ztkj.his.main.server");
		long begin = new Date().getTime();
		FileUtil dir = new FileUtil(s, t);
		try {
			dir.run();
			System.out.println("用时:" + (new Date().getTime() - begin));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
